<?php
/**
 * 微信粉丝模型
 * User: wyqiang
 * Date: 2015-09-06
 */
namespace Wx\Model;

use Common\Api\Wx\Wechat;
use Think\Exception;
use Think\Log;
use Think\Model\AdvModel;
use Common\Api\Wx\ErrorCode;

class WxFansModel extends AdvModel {
	
	//性别
	const SEX_UNKOWN = 0;//未知
	const SEX_MAN = 1;//男
	const SEX_WOMAN = 2;//女
	
	//是否关注（状态）
	const SUBSCRIBE_YES = 1;//关注
	const SUBSCRIBE_NO = 2;//取消关注


    /**
     * 绑定openid
     */
    public function bindOpenid($mobile, $openid){
    	$map = array('phone'=>$mobile);
    	$uInfo = D('Home/Member')->where($map)->find();

    	$condition = array( 'openid' => $openid );
    	$data = array( 'mobile'=>$mobile );
    	if($uInfo) $data['uid'] = $uInfo['uid'];

    	try{
            $flag = $this->where($condition)->save($data);//绑定手机号
            if($flag !== false){
            	$addrModel = D('Address');
            	$addr = $addrModel->where($condition)->find();

            	//若没有填写地址则增加默认地址
            	if(!$addr){
            		$addrData = array();
            		$addrData['openid'] = $openid;
            		$addrData['mobile'] = $mobile;
            		$addrData['is_default'] = $addrModel::IS_DEFAULT;

                    $addrModel->add($addrData);
				}
			}

            return true;
		}catch (Exception $e){
    		Log::write(__CLASS__ . __METHOD__. $e->getMessage(), Log::ERR);
    		return false;
		}
	}

	/**
	 * @param $id
	 * @return mixed
     */
	public function getUserInfoById($id) {
		return $this->find($id);
	}

	/**
	 * 通过有赞id获取所属推广人
	 * @param $fans_id
	 * @return mixed|string
     */
	public function getPromoter($fans_id){
		try{
			$map['youzan_id'] = $fans_id;
			$promoter = $this->where($map)->getField('promoter');
			//$sql = $this->getLastSql();

			return ($promoter) ? $promoter : '';
		}catch (Exception $e){
			return false;
		}

	}

	/**
	 * 根据手机号获取粉丝信息
	 * @param $wxid
	 * @param $mobile
	 * @return mixed
     */
	public function getFansInfoByMobile($wxid, $mobile){
		$map = array('subscribe' => 1);
		$map['wxid']	= $wxid;
		$map['mobile']	= $mobile;

		return $this->where($map)->find();
	}

	/**
	 * 过滤手机号
	 * @param $wxid
	 * @param $mobileArr
	 * @return array
     */
	public function filterMobiles($wxid, $mobileArr){
		$map = array('subscribe' => 1);
		$map['wxid']	= $wxid;
		$map['mobile']	= array('IN', $mobileArr);

		$res = $this->where($map)->select();
		$returnData = array();
		if($res){
			foreach ($res as $v){
				$returnData[$v['mobile']] = $v['openid'];
			}
		}

		return $returnData;
	}
	
	/**
	 * 取得粉丝总数
	 * $table_id:分表的索引；
	 * $where:条件
	 */
	public function getFansCount($wxid) {
		$where['subscribe'] = 1;//筛选 关注的用户
		if($wxid) $where['wxid'] = $wxid;
		if(!empty($where['tag_id'])) {
			return $this->join('LEFT JOIN __WX_FANS_TAG__ AS t ON f.openid = t.openid')
				->where($where)
				->count();
		}else{
			return $this->where($where)->count();
		}
	}
	
	/**
	 * $table_id:分表的索引；
	 * $where:条件
	 * $page:true,分页，默认检索全部
	 */
	public function getFansList($table_id,$where,$page=false) {
		$pagesize = 10;
		$where['subscribe'] = 1;
		if (is_numeric($page)) {
			return $this->where($where)->order("id desc")->limit($page)->select();
		} elseif ($page === true) {
			$page = I('p',1,'intval');
			if(!empty($where['tag_id'])) {
				return $this->alias('f')
					->join(
						'LEFT JOIN __WX_FANS_TAG__ AS t ON f.openid = t.openid'
					)
					->where($where)
					->group('f.openid')
					->order("f.id desc")
					->page("$page,$pagesize")
					->select();
			}else{
				return $this->where($where)->order("id desc")->page("$page,$pagesize")->select();
			}
		}
		return $this->field("`openid`,`nickname`")->where($where)->select();
	}
	
	/**
	 * 根据wxid和openid获得用户信息
	 * @param int $wxid
	 * @param varchar $openid
	 */
	public function getInfoByUniqueKey($wxid,$openid) {
		return $this->where(array('wxid'=>$wxid,'openid'=>$openid))->find();
	}
	
	
	/**
	 * 作用：外部静态调用
	 * 用户关注公众号时、记录用户数据
	 * 调用方式 $obj = new \Operate\Model\WxFansModel();$obj->subscribe($wxname,$openid);
	 * $wxname:微信公众号     $openid：关注用户id
	 */
	public function subscribe($mp_id, $openid, $promoter = '') {
		try{
			//通过微信名称获取微信绑定信息
			if (is_array($mp_id)) {
				$wxInfo = $mp_id;
			} else {
				$wxEntAppModel = D('WxMp');
				$wxInfo = $wxEntAppModel->getInfoById($mp_id);
			}
			if (!$wxInfo) {
				return false;
			}

			$apiObj = getWxObj($wxInfo);
			$data = $apiObj->getUserInfo($openid);
			if (!$data) {
				$data = array(
					'openid' => $openid,
					'wxid' => $wxInfo['mp_id'],
					'subscribe' => self::SUBSCRIBE_YES
				);
			} else {
				unset($data['language']);
				$data['openid'] = $openid;
				$data['wxid'] = $wxInfo['mp_id'];
				$data['subscribe'] = self::SUBSCRIBE_YES;
			}
			//增加推广员id
			if($promoter) $data['promoter'] = $promoter;
			$info = $this->getInfoByUniqueKey($data['wxid'],$data['openid']);
			if ($info) {
				$data = array_merge($info,$data);
				unset($data['id']);
				unset($data['wxid']);
				unset($data['openid']);
				$this->where(array('wxid'=>$wxInfo['mp_id'],'openid'=>$openid))->save($data);
			} else {
				$this->add($data);
			}
			//新关注用户 自动加入 无标签分组中
			$wxTagsModel = D('WxTags');
			$default_tag = $wxTagsModel->where(array('is_default'=>1,'wxid'=>$wxInfo['mp_id']))->find();
			if($default_tag){
				$fans_tag = array(
					'openid' => $openid,
					'tag_id' => $default_tag['id'],
					'create_time' => time()
				);

				$WxFansTagModel = D('WxFansTag');
				$add_fans_tag_flag = $WxFansTagModel->add($fans_tag);
				if($add_fans_tag_flag !== false){
					$fans_count_flag = $wxTagsModel->where(array('id'=>$default_tag['id']))->setInc('fans_count');
				}
			}

			return true;
		}catch (Exception $e){
			return false;
		}
	}
	
	/**
	 * 作用：外部静态调用
	 * 用户取消公众号时、将用户标记为未关注
	 * 调用方式 $obj = new \Operate\Model\WxFansModel();$obj->unSubscribe($wxname,$openid);
	 * $wxname:微信公众号     $openid：关注用户id
	 */
	public function unSubscribe($mp_id,$openid) {
		//通过微信名称获取微信绑定信息
		if (is_array($mp_id)) {
			$wxInfo = $mp_id;
		} else {
			$wxEntAppModel = D('WxMp');
			$wxInfo = $wxEntAppModel->getInfoById($mp_id);
		}
		if (!$wxInfo) {
			return false;
		}
		
		$data = array(
			'wxid' => $wxInfo['mp_id'],
			'openid' => $openid,
		);

		//检索这条记录
		$fansInfo = $this->where($data)->find();
		//更新关注状态
		if($fansInfo){
			if($this->where($data)->save(array('subscribe'=>2))){
				//查询标签关系
				$fans_tag = M('WxFansTag')->join('LEFT JOIN __WX_TAGS__ ON tag_id = __WX_TAGS__.id')
					->where(array('openid'=>$openid,'wxid'=>$wxInfo['mp_id']))->find();
				if($fans_tag){
					//删除标签关系
					if(M('WxFansTag')->where(array('openid'=>$openid))->delete()){
						//更新标签粉丝数
						M('WxTags')->where(array('id'=>$fans_tag['tag_id']))->setDec('fans_count');
					}

				}
			}
		}

		return true;
	}

    /**
     * 同步更新MP上的用户分组到平台
     */
    public function reflashFansGroup($mp_id) {
        //通过微信名称获取微信绑定信息
		if (is_array($mp_id)) {
			$wxInfo = $mp_id;
		} else {
			$wxEntAppModel = D('WxMp');
			$wxInfo = $wxEntAppModel->getInfoById($mp_id);
		}
		if (!$wxInfo) {
			return false;
		}

        //MP接口获得组别信息
        $param = array(
            'appid' => $wxInfo['app_id'],
            'appsecret' => $wxInfo['app_secret'],
			//'token' => $wxInfo['data_fetcher_token']
        );
        //$apiObj = new \Common\Api\Wx\Wechat($param);
        $apiObj = getWxObj($wxInfo);
        $data = $apiObj->getGroup();
        $c = 0;
        if ($data) {
            //格式化数据
            foreach ($data['groups'] as $v) {
                $list[] = array(
                    'wxid' => $wxInfo['mp_id'],
                    'wx_group_id' => $v['id'],
                    'name' => $v['name'],
                    'fans_count' => $v['count']
                );
                $c += $v['count'];
            }
            //删除原有的组别信息
            M('WxFansGroup')->where(array('wxid'=>$wxInfo['mp_id']))->delete();
            //记录数据库
            M('WxFansGroup')->addAll($list);
        }
        return $c;
    }

	/**
	 * 同步更新MP上的用户分组到平台
	 */
	public function reflashFansTags($mp_id) {
		//通过微信名称获取微信绑定信息
		if (is_array($mp_id)) {
			$wxInfo = $mp_id;
		} else {
			$wxEntAppModel = D('WxMp');
			$wxInfo = $wxEntAppModel->getInfoById($mp_id);
		}
		if (!$wxInfo) {
			return false;
		}

		$apiObj = getWxObj($wxInfo);
		$data = $apiObj->getTags(); //微信获取标签
		$c = 0;
		if ($data) {
			//加入默认标签
			$list[] = array(
				'wxid'       => $wxInfo['mp_id'],
				'wx_tag_id'  => '0',
				'name'       => '无标签',
				'fans_count' => '0',
				'create_time'=> date('Y-m-d H:i:s'),
				'is_default' => 1
			);
			$list[] = array(
				'wxid'       => $wxInfo['mp_id'],
				'wx_tag_id'  => 1,
				'name'       => '黑名单',
				'fans_count' => '0',
				'create_time'=> date('Y-m-d H:i:s'),
				'is_default' => 1
			);
			//格式化数据
			foreach ($data['tags'] as $v) {
				$list[] = array(
					'wxid' => $wxInfo['mp_id'],
					'wx_tag_id' => $v['id'],
					'name' => $v['name'],
					'fans_count' => $v['count'],
					'create_time' => date('Y-m-d H:i:s'),
					'is_default'  => 0
				);
				$c += $v['count'];
			}
			//删除原有标签对应关系
			$old_tags = M('WxTags')->field('id')->where(array('wxid'=>$wxInfo['mp_id']))->select();
			$tagIdArr = array_map(function($v){return $v['id'];},$old_tags);
			if(!empty($tagIdArr)){
				$map['tag_id'] = array('IN', $tagIdArr);
				M('WxFansTag')->where($map)->delete();
			}
			//删除原有的标签信息
			M('WxTags')->where(array('wxid'=>$wxInfo['mp_id']))->delete();
			//记录数据库
			M('WxTags')->addAll($list);
		}else{
			error_log("get tags from weixin error:" . $apiObj->errCode.ErrorCode::getErrText($apiObj->errCode)."\r\n", 3, "/tmp/wmj_test_log.log");
			return array('info'=>ErrorCode::getErrText($apiObj->errCode));
		}
		return $c;
	}
    
    /**
     * 解除绑定时，删除用户管理数据表中的数据
     */
    public function unBindMp($wxInfo) {
		//删除标签信息
		$tags = M('WxTags')->field('id')->where(array('wxid'=>$wxInfo['mp_id']))->select();
	    if($tags){
		    $tags_id = array_map(function($v){return $v['id'];},$tags);
		    M('WxTags')->where(array('wxid'=>$wxInfo['mp_id']))->delete();
		    M('WxFansTag')->where(array('tag_id'=>array('in',$tags_id)))->delete();
	    }

    	//删除用户数据
    	$this->where(array('wxid'=>$wxInfo['mp_id']))->delete();
    	
    	//删除用户同步时的缓存
    	$this->checkSynchro($wxInfo,null);
    }
    
    /**
     * $data:NULL:删除缓存；非空array：保存数据；空array（默认）:读取缓存
     * 监测用户数据是否同步、并记录last_openid;
     */
    public function checkSynchro($wxInfo,$data=array()) {
		//关闭同步功能时的判断
		if(C('SYNC_SWITCH') === false) {
			//检测是否有用户
			$count = $this->getFansCount($wxInfo['mp_id']);
			if ($count > 0) {
				return array('status' => $count);
			} else {
				return array('status' => false);
			}
		}

		//改用数据库形式
		if(is_array($data)){
			if($data){
				//设置
				if($wxInfo['mp_id']) {
					return M('WxMp')->where(array('mp_id'=>$wxInfo['mp_id']))->save(array('next_sync_user'=>json_encode($data)));
				}
			}else{
				$cache = M('WxMp')->field('next_sync_user')->where(array('mp_id'=>$wxInfo['mp_id']))->find();
				$cache = json_decode($cache['next_sync_user'],true);
				if (!$cache) {
					return array('status'=>false,'openid'=>'','count'=>0);
				}
				return $cache;
			}
		}else {
			//删除
			return M('WxMp')->where(array('mp_id'=>$wxInfo['mp_id']))->save(array('next_sync_user'=>''));
		}
    }
	/**
	 * $data:NULL 删除缓存，非空 int：保存数据，空array（默认）：读取缓存
	 * 检测是否有用户在同步粉丝
	 */
	public function checkIsSyncIng($data = array()){
		if (is_array($data)) {
			if ($data) {
				//设置
				return F("mp/is_syncing",$data);
			} else {
				//读取
				$cache = F("mp/is_syncing");
				if (!$cache) {
					return false;
				}
				return $cache;
			}
		} else {
			//删除
			return F("mp/is_syncing",null);
		}
	}
	/**
	 * 作用：外部静态调用
	 * 绑定公众号时，同步用户信息(批量)
	 * 调用方式 $obj = new \Operate\Model\WxFansModel();$obj->reflashFans();
	 * $wxname,$next_openid
	 */
	public function reflashFans($wxInfo) {
		if (!$wxInfo) {
			return array('status'=>false,'info'=>'公众号错误');
		}

		/*$is_syning = $this->checkIsSyncIng();
		if($is_syning['status'] === true && $is_syning['mp_id'] != $wxInfo['mp_id']){
			return array('status'=>false,'info'=>'其他公众号正在同步粉丝，请稍后再来。');
		}*/

		//检查是否同步过
		$r = $this->checkSynchro($wxInfo);
		if ($r['status'] === true) {
			return $r;
		} else {
			$next_openid = $r['openid'];
			$reflashedcount = $r['count'];
		}

		//从一条开始同步
		if (!$next_openid) {
            //如果没有next_openid的话，默认为是第一次同步，需要同步一次用户标签
            /*$tagresult = $this->reflashFansTags($wxInfo);
			if(!empty($tagresult['info'])){
				return array('status'=>false,'info'=>$tagresult['info']);
			}*/
			//删除已有的用户信息记录
			//$this->where(array('wxid'=>$wxInfo['mp_id']))->delete();
		}
		//获得接下去10000个openid @TODO getUserList
		//初始化微信操作对象
		$options = array (
			'token'             => $wxInfo['data_fetcher_token'],  // 填写你设定的key
			'appid'             => $wxInfo['app_id'],
			'appsecret'         => $wxInfo['app_secret']
		);

		$apiObj = new Wechat($options);
		$data = $apiObj->getUserList($next_openid);

        if (!$data && $apiObj->errCode) {
			return array('status'=>false,'info'=>ErrorCode::getErrText($apiObj->errCode));
		}
		$per = 100;
		if ($data) {
			$total = $data['total'];//关注该公众账号的总用户数
			$count = $data['count'];//拉取的OPENID个数，最大值为10000
			if ($count == 0) {
				$fData = array(
						'status' => true,
						'openid' => '',
						'count' => $reflashedcount
				);
				$this->checkSynchro($wxInfo,$fData);
				return array('status'=>true,'total'=>$total,'count' => $total,'next_openid' => '');
			}

			//拉去用户信息，一次最多只能拿到100个用户
			if (count($data['data']['openid']) > $per) {
				$openids = array_slice($data['data']['openid'],0,$per);
				$nextOpenid = $data['data']['openid'][$per-1];
			} else {
				$openids = $data['data']['openid'];
				$nextOpenid = '';
			}

			//批量获取用户基本信息 @TODO
			$r = $apiObj->getUserInfoBatchget($openids);
            $fans_list = array();
			$fans_tag_list = array();
            //如果有权限拿到用户信息的话，记录
			if ($r) {
				//查询所有标签列表（本地）
				//$tagsModel = D('WxTags');
				//$tagwxid = $tagsModel->getTagsWxidId($wxInfo['mp_id']);
				//格式化数据
				foreach ($r['user_info_list'] as $v) {
                    unset($v['language']);
                    $v['wxid'] = $wxInfo['mp_id'];
					//处理用户标签关系
					/*if(!empty($v['tagid_list'])){
						$tagids = $v['tagid_list'];
						foreach($tagids as $tid){
							$obj = array();
							$obj['openid'] = $v['openid'];
							$obj['tag_id'] = $tagwxid[$tid];
							$obj['create_time'] = time();
							$fans_tag_list[] = $obj;
						}
					}else{
						放入无标签组
						if($tagwxid['0']) {
							$fans_tag_list[] = array(
								'openid' => $v['openid'],
								'tag_id' => $tagwxid['0'],
								'create_time' => time()
							);
						}
					}*/
                    $fans_list[] = $v;
				}
			//没有的话结束操作
			} else {
				//释放 同步缓存
				$this->checkIsSyncIng(null);
				return array('status'=>false,'info'=>'没有获取用户信息的权限');
			}

            //设置锚点
            if ($nextOpenid) {
            	$fData = array(
            		'status' => false,
            		'openid' => $nextOpenid,
            		'count' => $reflashedcount + $per
            	);
            } else {
            	$fData = array(
            		'status' => true,
            		'openid' => '',
            		'count' => $reflashedcount + $per
            	);
				//同步完后取消 正在同步的缓存 让别人继续能同步
				$this->checkIsSyncIng(null);
            }

            $this->checkSynchro($wxInfo,$fData);
			$this->_addList($fans_list);

            return array('status'=>true,'total'=>$total,'count' => $reflashedcount + $per,'next_openid' => $nextOpenid);
		}
		//同步完成的操作
		$fData = array(
				'status' => true,
				'openid' => '',
				'count' => 0
		);
		$this->checkSynchro($wxInfo,$fData);

		//同步完后取消 正在同步的缓存 让别人继续能同步
		$this->checkIsSyncIng(null);
		return array('status'=>true,'total'=>0,'count' => 0,'next_openid' => '');
	}

	/**
	 *
	 * @param $fans_list
	 * @param array $fans_tag_list
	 * @return bool|mixed
     */
	private function _addList($fans_list, $fans_tag_list = array()){
		if(!$fans_list) return false;

		//批量插入粉丝
		$flag = true;
		foreach ($fans_list as $fans){
			$flag = $this->add($fans, array(), true);
		}

		//批量添加用户标签关系
		if($fans_tag_list) {
			M('WxFansTag')->addAll($fans_tag_list);
		}
		//记录最大ID
		$maxId = $this->getLastInsID();
		//import('Operate.Model.WxFansIndexModel');
		//M('WxFansIndex')->where(array('table_id'=>$wxInfo['table_id']))->save(array('max_id'=>$maxId));

		return $flag;
	}

	//同步积分操作
	private function synScore($wxInfo){
		//同步积分
		$fansSync = D('FansSync');
		$syncScoreStatus = $fansSync->syncFansPoints($wxInfo['mp_id']);
		//保存积分同步状态
		D('WxMp')->where(array('mp_id'=>$wxInfo['mp_id']))->save(array('points_sync_status'=>$syncScoreStatus));
	}
	/**
	 * 转移用户到某个用户组
	 * @param int $wxInfo 公众号信息
	 * @param int $group_id 微信中的组别ID
	 * @param array $fans_ids 本平台的fansID
	 */
	public function moveFans($wxInfo,$group_id,$fans_ids) {
		//API接口，转移用户
		$map = array(
			'id' => array('in',$fans_ids)
		);
		$openidList = $this->field('`groupid`,`openid`')->where($map)->select();
		$groupNum = array($group_id=>0);
		if (empty($openidList)) {
			return false;
		} else {
            foreach ($openidList as $v) {
            	if ($v['groupid'] == $group_id) {
            		continue;
            	}
            	if (isset($groupNum[$v['groupid']])) {
            		$groupNum[$v['groupid']]--;
            	} else {
            		$groupNum[$v['groupid']] = -1;
            	}
            	$groupNum[$group_id]++;
                $list[] = $v['openid'];
            }
        }//print_r($groupNum);print_r($list);exit;
        if (!$list) {
        	return false;
        }
		$param = array(
				'appid' => $wxInfo['app_id'],
				'appsecret' => $wxInfo['app_secret']
		);
		//$apiObj = new \Common\Api\Wx\Wechat($param);
		$apiObj = getWxObj($wxInfo);
		$r = $apiObj->batchUpdateGroupMembers($group_id,$list);

		if ($r) {
            //设置粉丝的组别
			$this->where(array('id'=>array('in',$fans_ids)))->save(array('groupid'=>$group_id));
            //更新组别的粉丝数量
            foreach ($groupNum as $k => $v) {
            	if ($v > 0) {
            		M('WxFansGroup')->where(array('wxid' => $wxInfo['mp_id'],'wx_group_id'=>$k))->setInc('fans_count',$v);
            	} elseif($v < 0) {
            		M('WxFansGroup')->where(array('wxid' => $wxInfo['mp_id'],'wx_group_id'=>$k))->setDec('fans_count',abs($v));
            	}
            }
			return true;
		}
		return false;
	}
	
	/**
	 * 性别分布
	 * $wxinfo公众号信息
	 * $time_start 2015-10-29
	 * $time_end	2015-10-29
	 */
	public function getSexStatistics($wxInfo,$time_start,$time_end) {
		if($time_start&&$time_end) {
			$time_start = strtotime($time_start);
			$time_end = strtotime($time_end) + 86400;
			$where = array(
				'subscribe_time' => array(
					array('EGT', $time_start),
					array('ELT', $time_end),
				),
				'wxid' => $wxInfo['mp_id']
			);
		}else{
			$where = array(
				'wxid' => $wxInfo['mp_id']
			);
		}
		return $this->field("`sex` as label,count(`id`) as value")
			->where($where)
			->group("`sex`")
			->select();
	}
	
	/**
	 * 城市分布
	 * $wxinfo公众号信息
	 * $time_start 2015-10-29
	 * $time_end	2015-10-29
	 */
	public function getProvinceStatistics($wxInfo,$time_start,$time_end) {
		$time_start = strtotime($time_start);
		$time_end = strtotime($time_end) + 86400;
		$where = array(
			'subscribe_time' => array(
					array('EGT',$time_start),
					array('ELT',$time_end),
			),
			'wxid' => $wxInfo['mp_id']
		);
	
		return $this->field("`province` as label,count(`id`) as value")
		->where($where)
		->group("`province`")
		->select();
	}
}
?>
